package com.upstairstechnology.oi.determination;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Factory methods to create integration checks.
 * 
 * @author Jeff Jensen
 */
public class IntegrationCheckFactory {
    /** Logger instance. */
    private static final Logger LOGGER =
            LoggerFactory.getLogger(IntegrationCheckFactory.class);

    /**
     * Factory method specifying branchspec.
     * 
     * @param branchspec
     *            The branchspec name. The string is trimmed.
     * @return A new instance with the specified branch spec value set.
     */
    public static IntegrationCheck newInstance(String branchspec) {
        IntegrationCheck check = new IntegrationCheck();
        check.setBranchspec(branchspec.trim());
        return check;
    }

    /**
     * Factory method specifying source and target codelines.
     * 
     * @param source
     *            The source codeline. The string is trimmed.
     * @param target
     *            The target codeline. The string is trimmed.
     * @return A new instance with the specified branch spec value set.
     */
    public static IntegrationCheck newInstance(String source, String target) {
        IntegrationCheck check = new IntegrationCheck();
        check.setSourceCodeline(source.trim());
        check.setTargetCodeline(target.trim());
        return check;
    }

    /**
     * Make an empty set of integration checks.
     * 
     * @return An empty set of integration checks.
     */
    public static Set<IntegrationCheck> makeEmptySet() {
        return new HashSet<IntegrationCheck>();
    }

    /**
     * Make a set of integration checks from string arrays of branchspec names
     * and source and target codeline names.
     * 
     * @param branchspecArray
     *            The branchspec names.
     * @param sourceArray
     *            The array of source codeline names.
     * @param targetArray
     *            The array of target codeline names.
     * @return A set of integration checks from a string array of branchspec
     *         names.
     * @throws IllegalArgumentException
     *             When either branchspec or source and target codeline names
     *             are not specified.
     */
    public static Set<IntegrationCheck> makeSet(String[] branchspecArray,
            String[] sourceArray, String[] targetArray) {
        final Set<IntegrationCheck> fullSet = makeEmptySet();

        if (branchspecArray == null && sourceArray == null
                && targetArray == null) {
            final String msg =
                    "Must specify either branchspecs or"
                            + " source and target codelines.";
            throw new IllegalArgumentException(msg);
        }

        if (branchspecArray != null) {
            final Set<IntegrationCheck> subset = makeSet(branchspecArray);
            fullSet.addAll(subset);
        }

        if (sourceArray != null && targetArray != null) {
            final Set<IntegrationCheck> subset =
                    makeSet(sourceArray, targetArray);
            fullSet.addAll(subset);
        }

        return fullSet;
    }

    /**
     * Make a set of integration checks from a string array of branchspec names.
     * 
     * @param branchspecArray
     *            The branchspec names.
     * @return A set of integration checks from a string array of branchspec
     *         names.
     */
    public static Set<IntegrationCheck> makeSet(String[] branchspecArray) {
        final Set<IntegrationCheck> set = makeEmptySet();

        for (String checkString : branchspecArray) {
            IntegrationCheck check =
                    IntegrationCheckFactory.newInstance(checkString);
            set.add(check);
        }

        LOGGER.debug("made set={}", set);

        return set;
    }

    /**
     * Make a set of integration checks from string arrays of source and target
     * codeline names.
     * 
     * @param sourceArray
     *            The array of source codeline names.
     * @param targetArray
     *            The array of target codeline names.
     * @return A set of integration checks from a string array of branchspec
     *         names.
     */
    public static Set<IntegrationCheck> makeSet(String[] sourceArray,
            String[] targetArray) {
        int sourceLen = sourceArray.length;
        int targetLen = targetArray.length;

        LOGGER.debug("sourceArray.length={}, targetArray.length={}", sourceLen,
                targetLen);
        LOGGER
                .debug("sourceArray={}, targetArray={}", sourceArray,
                        targetArray);

        if (sourceLen != targetLen) {
            final String msg =
                    "Integration check source and target codeline lists"
                            + " do not have same number of entries:"
                            + " source count=" + sourceLen + ", target count="
                            + targetLen + ", sources="
                            + Arrays.toString(sourceArray) + ", targets="
                            + Arrays.toString(targetArray);
            throw new IllegalArgumentException(msg);
        }

        final Set<IntegrationCheck> set = makeEmptySet();

        for (int i = 0; i < sourceLen; i++) {
            IntegrationCheck check =
                    IntegrationCheckFactory.newInstance(sourceArray[i],
                            targetArray[i]);
            set.add(check);
        }

        LOGGER.debug("made set={}", set);

        return set;
    }
}
